上回我們大致上規劃了我們所需要的API測試架構,基本架構如下:
[Theory]
[ClassData(nameof(GetProductList_Scenrio))]
public void TestCase1(Scenario payload)
{
var actual = GetProductList(payload.Price, payload.Category);
var expected = payload.Expected_GetProductList;
actual.Should().BeEquivalentTo(expected);
}
為了在建立的類別中取得物件,我先建立一個測試情境的基底類別,語法如下(可參考此篇文章做改寫):
public abstract class ScenarioBase : IEnumerable<object[]>
{
public abstract IEnumerator<object[]> GetEnumerator();
IEnumerator<object[]> IEnumerable<object[]>.GetEnumerator()
=> GetEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
}
當然因為做為基底,我將方法作為抽象,接著依照需求先建立測試情境類別(Scenario),並且將需要的欄位(需要用的參數)以及預期結果一併加入,結果如下:
public class Scenario
{
public decimal Price { get; set; }
public string Category { get; set; }
public List<Product> Expected_GetProductList { get; set; }
}
接著我們要加入專屬的測試物件,裡面包含了我的測試Case要用的資料以及該筆資料的預期結果,外殼語法如下:
public class GetProductList_Scenrio : ScenarioBase
{
public override IEnumerator<Scenario[]> GetEnumerator()
{
yield return new Scenario[] {
new ()
{
},
};
}
}
完成之後我們設計的API測試架構就完成了,接著我們來輸入與之前相同的測試資料,如下:
public override IEnumerator<Scenario[]> GetEnumerator()
{
yield return new Scenario[] {
new ()
{
Price = 100,
Category = "電器",
Expected_GetProductList = new List<Product>() {
new Product() {
ProductID=1,
Name ="吹風機",
Price=100,
Category = "電器"
,IsSale=true},}
},
};
}
最後嘗試執行我們建立的測試Case可以通過,當然我們所使用的是yield return,所以我們可以執行多筆的測試Case,我額外加入一組API會回傳空物件的資料,內容如下:
public class GetProductList_Scenrio : ScenarioBase
{
public override IEnumerator<Scenario[]> GetEnumerator()
{
yield return new Scenario[] {
new ()
{
Price = 100,
Category = "電器",
Expected_GetProductList = new List<Product>() {
new Product() {
ProductID=1,
Name ="吹風機",
Price=100,
Category = "電器"
,IsSale=true},}
},
};
yield return new Scenario[] {
new ()
{
Price = 80,
Category = "傢具",
Expected_GetProductList = new List<Product>() {}
},
};
}
}
成功通過測試後我們可以打開測試總管看看測試的細節,可以得知我們測試也是同一個Case跑了兩筆資料,如下:
最後,之前有提到過FluentAssertions中的BeEquivalentTo可以驗證物件的正確性,但是不包含其中的排序(當然如果不需驗證排序就不考慮),也就是說{1,2,3}={2,1,3},所以我們需要加入額外的option來做限制,語法改寫如下:
[Theory]
[ClassData(typeof(GetProductList_Scenrio))]
public void TestCase1(Scenario payload)
{
var actual = GetProductList(payload.Price, payload.Category);
var expected = payload.Expected_GetProductList;
actual.Should().BeEquivalentTo(expected, option => option.WithStrictOrdering());
}
以上我們完成了API的簡易測試框架,如此當我們做測試的時候,我只需要專注在測試資料來源以及預期結果,而不需要動到測試Case裡面的內容。
更多小知識,我們下次見~~